/*
 * TcpClient.as
 *
 * Copyright (C) 2011 - Dr.NP
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package bsp.net
{
	import flash.net.Socket;
	import flash.utils.ByteArray;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.ProgressEvent;
	
	public class TcpClient
	{
		private var sck : Socket;
		
		private var m_on_connect : Function;
		private var m_on_close : Function;
		private var m_on_io_error : Function;
		private var m_on_sec_error : Function;
		private var m_on_data : Function;
		private var m_on_cmd : Function;
		private var b_on_connect : Boolean = false;
		private var b_on_close : Boolean = false;
		private var b_on_io_error : Boolean = false;
		private var b_on_sec_error : Boolean = false;
		private var b_on_data : Boolean = false;
		private var b_on_cmd : Boolean = false;
		
		public function TcpClient(addr : String, port : uint)
		{
			this.sck = new Socket();
			this.sck.addEventListener(Event.CONNECT, this._on_connect);
			this.sck.addEventListener(Event.CLOSE, this._on_close);
			this.sck.addEventListener(IOErrorEvent.IO_ERROR, _on_io_error);
			this.sck.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _on_sec_error);
			this.sck.addEventListener(ProgressEvent.SOCKET_DATA, this._on_data);
			
			this.sck.connect(addr, port);
			
			return;
		}
		
		public function send(data : ByteArray) : uint
		{
			this.sck.writeBytes(data);
			this.sck.flush();
			
			return data.length;
		}
		
		// Functions sets
		public function set on_connect(f : Function) : void
		{
			this.m_on_connect = f;
			this.b_on_connect = true;
			
			return;
		}
		
		public function set on_close(f : Function) : void
		{
			this.m_on_close = f;
			this.b_on_close = true;
			
			return;
		}
		
		public function set on_io_error(f : Function) : void
		{
			this.m_on_io_error = f;
			this.b_on_io_error = true;
			
			return;
		}
		
		public function set on_sec_error(f : Function) : void
		{
			this.m_on_sec_error = f;
			this.b_on_sec_error = true;
			
			return;
		}
		
		public function set on_data(f : Function) : void
		{
			this.m_on_data = f;
			this.b_on_data = true;
			
			return;
		}
		
		public function set on_cmd(f : Function) : void
		{
			this.m_on_cmd = f;
			this.b_on_cmd = true;
			
			return;
		}
		
		// Callback functions
		private function _on_connect(e : Event) : void
		{
			if (this.b_on_connect)
			{
				this.m_on_connect();
			}
			
			return;
		}
		
		private function _on_close(e : Event) : void
		{
			if (this.b_on_close)
			{
				this.m_on_close();
			}
			
			return;
		}
		
		private function _on_io_error(e : IOErrorEvent) : void
		{
			if (this.b_on_io_error)
			{
				this.m_on_io_error();
			}
			
			return;
		}
		
		private function _on_sec_error(e : SecurityErrorEvent) : void
		{
			if (this.b_on_sec_error)
			{
				this.m_on_sec_error();
			}
			
			return;
		}
		
		private function _on_data(e : ProgressEvent) : void
		{
			if (!this.b_on_data)
			{
				return;
			}
			
			var data : ByteArray = new ByteArray();
			var rtn : Object;
			this.sck.readBytes(data);
			
			while (data.bytesAvailable)
			{
				rtn = this.m_on_data(data);
				if (!rtn)
				{
					break;
				}
				
				if (this.b_on_cmd)
				{
					this.m_on_cmd(rtn);
				}
			}
			
			return;
		}
	}
}